package com.jade.bss.customer.menu.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.bss.customer.menu.Menu;
import com.jade.bss.customer.menu.MenuDao;
import com.jade.bss.customer.menu.MenuManager;
import com.jade.bss.base.BssException;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Order;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.util.PagingList;
import org.springframework.transaction.annotation.Transactional;

/**
 * 菜单管理接口实现。
 */
@Named("bss_menuManager")
public class MenuManagerImpl implements MenuManager
{
    private MenuDao menuDao;

    @Inject
    public void setMenuDao(@Named ("bss_menuDao") MenuDao menuDao)
    {
        this.menuDao = menuDao;
    }

    protected void checkName(Menu menu)
            throws BssException
    {
        Criteria criteria = new Criteria(0, 1);
        criteria.add(Restrictions.eq("pid", menu.getPid()));
        criteria.add(Restrictions.eq("name", menu.getName()));
        List<Menu> categories = list(criteria, false);
        if (!categories.isEmpty() && categories.get(0).getId() != menu.getId()) {
            throw new BssException("err.bss.menu.name_conflict", "name conflict", null,
                    menu.getName());
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void add(Menu menu)
            throws BssException
    {
        checkName(menu);
        menu.setCreationDate(new Date());
        menu.setUpdateDate(menu.getCreationDate());
        menuDao.add(menu);
        List<Menu> children = menu.getChildren();
        if (children != null) {
            for (Menu child : children) {
                child.setPid(menu.getId());
                menuDao.add(child);
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void update(Menu menu)
            throws BssException
    {
        checkName(menu);
        Date now = new Date();
        menu.setUpdateDate(now);
        menuDao.update(menu);
    }

//    @TransactionAttribute
//    @Transactional (rollbackFor = Throwable.class)
//    public void updateStatus(int status, long... ids)
//            throws BssException
//    {
//        for (long id : ids) {
//            Menu menu = get(id, false);
//            if (menu != null) {
//                menu.setStatus(status);
//                menu.setUpdateDate(new Date());
//                menuDao.update(menu);
//            }
//        }
//    }

    public Menu get(long id, boolean children)
    {
        Menu menu = menuDao.get(id);
        if (!children) {
            return menu;
        }
        if (menu == null) {
            return null;
        }
        menu.setChildren(listChildren(menu.getId(), children));
        return menu;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void remove(long... ids)
            throws BssException
    {
        for (long id : ids) {
            Menu menu = get(id, true);
            if (menu != null) {
                if (menu.hasChild()) {
                    throw new BssException("err.bss.menu.has_child", "menu has child", null,
                            menu.getName());
                }
                menuDao.remove(menu);
            }
        }
    }

    public List<Menu> listChildren(long parentId, boolean recursion)
    {
        Criteria criteria = new Criteria();
        criteria.add(Restrictions.eq("pid", parentId));
        criteria.addOrder(Order.desc("sortCode"));
        return list(criteria, recursion);
    }

    public List<Integer> listChildrenIds(long parentId, boolean recursion)
    {
        List<Menu> categories = listChildren(parentId, recursion);
        List<Integer> ids = new ArrayList<Integer>();
        addIdToList(ids, categories);
        return ids;
    }

    protected void addIdToList(List<Integer> ids, List<Menu> categories)
    {
        for (Menu menu : categories) {
            ids.add(menu.getId());
            if (menu.getChildren() != null) {
                addIdToList(ids, menu.getChildren());
            }
        }
    }

    public List<Menu> list(Criteria criteria, boolean children)
    {
        List<Menu> list = menuDao.list(criteria);
        if (!children) {
            return list;
        }
        for (Menu menu : list) {
            menu.setChildren(listChildren(menu.getId(), true));
        }
        return list;
    }

    public PagingList<Menu> query(Criteria criteria, boolean children)
    {
        PagingList<Menu> list = menuDao.query(criteria);
        if (!children) {
            return list;
        }
        for (Menu menu : list) {
            menu.setChildren(listChildren(menu.getId(), true));
        }
        return list;
    }

}
